function tr = periodicreturns(trprc, p)
%PERIODICRETURNS Total returns from total return prices.
%   TR = PERIODICRETURNS(TRPRC, P) calculates the total returns for a 
%   periodicity specified by the user from a daily total return price series .  
%
%   TR = PERIODICRETURNS(TRPRC) calculates the daily total returns from a 
%   daily total return price series .  
%
%   Inputs:
%      TRPRC - M x (N + 1) matrix consisting of date numbers in column 1 and total
%      return price data in the remaining columns.  N is the number of 
%      securities.
%
%   Optional Inputs:
%      P - Periodicity flag used to compute total returns.  P can be 
%          'd' for daily values (default value)
%          'm' for monthly values
%
%   Outputs:
%		TR - P x N matrix consisting of either
%			Date numbers in column 1 and daily return values in the remaining columns
%			or
%			Month-end date numbers in column 1 and monthly return values in the remaining columns.
%
%	Notes:
%		Although input returns can have dates in either ascending or descending order, output total
%		returns in TR have dates in ascending order with the earliest date in the first row of TR
%		and the most recent date in the last row of TR.
%
%   See also TOTALRETURNPRICE.

%       Copyright 1995-2008 The MathWorks, Inc.
%       $Revision: 1.1.6.3 $   $Date: 2008/05/12 21:25:11 $

if nargin < 2
  p = 'd';
end

%Number of securities
numsec = size(trprc,2)-1;

trprc = sortrows(trprc);

%Calculate monthly returns for one security at a time in case of mismatched dates
tmptr = cell(numsec,1);

switch p
    case 'd'
      for i = 1:numsec
        tmptr{i} = dailyreturnspersecurity(trprc(:,[1,i+1]));
      end
    case 'm'
      for i = 1:numsec
        tmptr{i} = monthlyreturnspersecurity(trprc(:,[1,i+1]));
      end
    otherwise
      error('finance:finance:periodSpecError','Period must be ''d'' or ''m''.')
end

%Get unique date list
tmpdates = tmptr{1}(:,1);
for i = 2:numsec
  tmpdates = unique([tmpdates;tmptr{i}(:,1)]);
end

%Preallocate output
tr = nan(length(tmpdates),numsec+1);
tr(:,1) = tmpdates;
for i = 1:numsec
  [c,ai,bi] = intersect(tmpdates,tmptr{i}(:,1));
  tr(ai,i+1) = tmptr{i}(bi,2);
end
  
    
function tr = dailyreturnspersecurity(trprc)
%DAILYRETURNPERSECURITY Daily total returns for single security.

%Remove NaN's from data
trprc(isnan(trprc(:,2)),:) = [];
maxindex = size(trprc,1);

%convert to total returns
tr = [trprc(:,1) trprc(:,2)];
pp0 = tr(1,2);
for tindex = 2:maxindex
    pp = trprc(tindex,2);   
    tr(tindex,2) = (pp - pp0)/pp0;
    pp0 = pp;
end

tr(1,:) = [];


function tr = monthlyreturnspersecurity(trprc)
%MONTHLYRETURNPERSECURITY Montly total returns for single security.

%Remove NaN's from data
trprc(isnan(trprc(:,2)),:) = [];
maxindex = size(trprc,1);

% find month-end dates and obtain month-end total return prices
tr = [];
mdata = month(trprc(:,1));
for tindex = 1:maxindex
    if tindex < maxindex
        if mdata(tindex) ~= mdata(tindex + 1)
            tdate = lbusdate(year(trprc(tindex,1)),month(trprc(tindex,1)));
            tr = [tr ; [tdate, trprc(tindex,2) ]];		%#ok
        end
    else
        if eomday(year(trprc(tindex,1)),month(trprc(tindex,1))) - day(trprc(tindex,1)) < 3
            tdate = lbusdate(year(trprc(tindex,1)),month(trprc(tindex,1)));
            tr = [tr ; [tdate, trprc(tindex,2) ]];		%#ok
        end
    end
end

%convert to monthly total returns
maxindex = size(tr,1);
pp0 = tr(1,2);
for tindex = 2:maxindex
    pp = tr(tindex,2);   
    tr(tindex,2) = (pp - pp0)/pp0;		%#ok
    pp0 = pp;
end

tr(1,:) = [];
